import os
import platform
import socket
import struct
import json
import sys


class Client(socket.socket):
    def __init__(self, target_ip, target_port):
        super().__init__()
        self.target_ip = target_ip
        self.target_port = target_port

    def initilize(self):
        """客户端初始化连接"""
        server_ip_port = (self.target_ip, self.target_port)
        print(f'正在连接服务端 {server_ip_port}')
        self.connect(server_ip_port)
        print(f'连接服务端成功')

    def start(self):
        return ClientLoop(self).run_forever()

    def send_msg(self, send_msg, path=None):
        """发送请求消息"""
        bytes_dic = json.dumps(send_msg).encode("utf8")
        header = struct.pack("i", len(bytes_dic))
        self.send(header)
        self.send(bytes_dic)
        if path:
            with open(path, "rb") as f:
                for line in f:
                    self.send(line)

    def recv_msg(self):
        """接受请求消息"""
        header = self.recv(4)
        back_dic = json.loads(self.recv(struct.unpack("i", header)[0]).decode("utf8"))
        return back_dic

    def recv_file(self, path, file_length):
        """接受下载文件"""
        print("文件传输中>>>....")
        if not os.path.exists(path):
            with open(path, 'w') as f:
                pass

        for _ in range(0xfffffff):
            with open(path, "ab") as w:
                content = self.recv(4096)
                w.write(content)
                file_length -= len(content)
                if file_length <= 0:
                    break
        print("下载完毕！")


class ClientLoop():

    def __init__(self, client):
        self.path = self.current_win_path()
        self.client = client

    def current_win_path(self):
        current_win = platform.system()

        if 'windows' in current_win.lower():
            return 'c://'
        else:
            return '/'

    def run_forever(self):
        """死循环处理和服务端通信"""
        while True:

            content = input(f"{self.path}：")
            if not content:
                continue

            content_list = [val.strip() for val in content.split(" ")]
            send_order = {
                "order": content_list[0],
                "order_content": content_list[1:]
            }
            self.client.send_msg(send_order)
            back_msg = self.client.recv_msg()

            result = back_msg.get("result", False)
            self.path = back_msg.get("path") if back_msg.get("path") else self.path

            if not result:
                sys.stderr.write(back_msg.get("msg", "未知错误！") + "\n")
            else:
                data = back_msg.get("data", {}).get("data", None)
                if isinstance(data, list):
                    for index, name in enumerate(data, start=1):
                        print(index, name)
                elif isinstance(data, str):
                    print(data)
                elif isinstance(data, dict):
                    print(data)
                    if "size" in data:
                        file_name = data.get("file_name", "")
                        size = data.get("size", 0)
                        path = f"files/{file_name}"
                        self.client.recv_file(path=path, file_length=size)
                else:
                    print(data)
                    # func(data)
                    pass
